﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace Util
{
	/// <summary>
	/// Util for Exp
	/// </summary>
	public static class UtilExp
	{
		/// <summary>
		/// Return constant expression c=>true.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <returns>expression</returns>
		public static Expression<Func<T, bool>> ExprTrue<T>()
		{
			return c => true;
		}
		/// <summary>
		/// Return constant expression c=>false.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <returns>expression</returns>
		public static Expression<Func<T, bool>> ExprFalse<T>()
		{
			return c => false;
		}
		/// <summary>
		/// Extents expression with "AndAlso"
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="expr1"></param>
		/// <param name="expr2"></param>
		/// <returns></returns>
		public static Expression<Func<T, bool>> ExprAnd<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
		{
			// 将expr2的参数cast到expr1的参数
			var exprInvoke = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
			// 将expr1的表达式主体部分和expr2的主体部分逻辑合并
			var exprCombine = Expression.AndAlso(expr1.Body, exprInvoke);
			// 将expr1的参数应用到最后的表达式
			return Expression.Lambda<Func<T, bool>>(exprCombine, expr1.Parameters);
		}
		/// <summary>
		/// Extents expression with "OrElse"
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="expr1"></param>
		/// <param name="expr2"></param>
		/// <returns></returns>
		public static Expression<Func<T, bool>> ExprOr<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
		{
			var exprInvoke = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
			var exprCombine = Expression.OrElse(expr1.Body, exprInvoke);
			return Expression.Lambda<Func<T, bool>>(exprCombine, expr1.Parameters);
		}
		/// <summary>
		/// convert list of sort condition to dic
		/// </summary>
		/// <typeparam name="T">class to sort</typeparam>
		/// <param name="funcList">condition</param>
		/// <param name="boolList">asce or desc</param>
		/// <returns></returns>
		public static Dictionary<Func<T, object>, bool> SpliceSort<T>(IList<Func<T, object>> funcList, IList<bool> boolList)
		{
			if (boolList.Count != funcList.Count)
				throw new ArgumentException("Count of sort and func' do not match.");
			Dictionary<Func<T, object>, bool> dic = new Dictionary<Func<T, object>, bool>();
			for (int i = 0; i < funcList.Count; i++)
				dic.Add(funcList[i], boolList[i]);
			return dic;
		}
	}
}